package md.specialEqp.inspect;

import md.specialEqp.Eqp;
import md.system.User;
import org.fjsei.yewu.jpa.ProjectionRepository;
import org.fjsei.yewu.jpa.QuerydslNcExecutor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.lang.Nullable;

import jakarta.persistence.QueryHint;
import java.util.List;
import java.util.Optional;
import java.util.UUID;


//缺省情形，这个类可以是空的。
//定制数据库各个模型=表的SQL操作。ProjectionRepository<Unit, UUID>,QuerydslNcExecutor<Unit>, JpaRepository<Unit, UUID>


public interface IspRepository extends ProjectionRepository<Isp, UUID>, QuerydslNcExecutor<Isp>, JpaRepository<Isp, UUID>, JpaSpecificationExecutor<Isp> {
    List<Isp> findByIspMen(User ispmen);
//    List<Isp> getByDev_IdOrderById(Long dev);

    @QueryHints(value = { @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_CACHEABLE, value = "true") } )
    List<Isp> findAll(@Nullable Specification<Isp> spec);

    //List<Isp> getByDev_IdAndTask_IdOrderByNextIspDate(Long dev, Long task);

    Isp findTopByDevAndNo(Eqp eqp,String no);
    //Isp findTopByDevAndNoOrderByIspDateDesc(Eqp eqp,String no);

    Optional<Isp> findByNo(String no);
    //随意的类型？可以返回：返回类型 <T> 必须和后面的Class<T>变量的T类型一致！ 支持IspDto2 isp= iSPRepository.findByNo("", IspDto2.class).get();若T改成Isp就和普通一样慢。
    <T> Optional<T> findByNo(String no, Class<T> type);
    <T> Optional<T> readAllByNo(String no, Class<T> type);

    //【神奇意外#Repository】 Interface-based实体类的动态投影技术；Slice<IspDto2>  ispSlice= iSPRepository.readAllBy(IspDto2.class);性能提升到极点。
    <T> Slice<T> readAllBy(Class<T> type);
    //<T> Slice<T> readAllBy(Class<?> type);  //报错At least 1 parameter(s) provided but only 0 parameter(s) present in query #必须一样类型

    //返回的Slice数据若pageable没有设置排序Order的：实体顺序可能因为该表的某记录修改而发生变动的。
    //【官方文档】5.1.3. Query Methods  https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#appendix.query.method.subject
    //JPA框架支持。Slice<IspDto2>  ispSlice= iSPRepository.readAllBy(pageable,IspDto2.class); 但是IspDto2读取出来的Unit进一步也是走原来的路子=Unit(id)要获取很多的嵌套关联字段。
    //【根据实际性能抉择】type若是采用interface投影：返回的Slice实际是代理#而且还会主动拉取更多嵌套关联的字段的； 反而type若用DTO class类来更能够简结的，不会主动获得更多嵌套关联字段。
   //这里T任意类型, 真的可以减少select语句输出的字段数量。
    <T> Slice<T> readAllBy(Pageable pageable,Class<T> type);            //不能改成:Class<?> type报错!

    //这个没有重载提示符号： 无法自定义生成的！ ；没重载的基本方法不能用于投影: <T> Slice<T> findAll(Class<T> type);
    //@Query(value = "select c from Isp c") No converter found capable of converting from type [md.specialEqp.inspect.Isp] to type [md.specialEqp.inspect.IspDto2]
    @Query(value = "select c.* from Isp c",  nativeQuery = true)
    <T> Slice<T> findAll(Pageable pageable, Class<T> type);     //报错！行不通啊 No Dialect mapping for JDBC type: 1111;针对findAll没法 Class<T> type这么干
}


/*
 支持定义成 Stream<User> readAllByFirstnameNotNull();
    try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
        stream.forEach(…);
    }    #不同于 Streamable<T>的？
 异步支持，但Asynchronous 不同于 reactive！
 @Async
 CompletableFuture<User> findOneByFirstname(String firstname);
 *同名字混淆的： @Component("specialCustom")配合@Component("specialCustomImpl")区分； xxxImpl名字
 * @Enable${store}Repositories{repositoryBaseClass =}
 * @EnableSpringDataWebSupport 配合 Spring HATEOAS=RestTemplate；
  @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
  User findByLastnameOrFirstname(@Param("lastname") String lastname, @Param("firstname") String firstname);
 @Query("select u from #{#entityName} u where u.lastname = ?1")
  List<User> findByLastname(String lastname);
   @Query("select u from User u where u.firstname = ?1 and u.firstname=?#{[0]} and u.emailAddress = ?#{principal.emailAddress}")
  List<User> findByFirstnameAndCurrentUserWithCustomQuery(String firstname);
  @Modifying  配套 only  @Query;
上面尝试是Class-based Projections (DTOs)方案，比起这个 projection interfaces接口方案,不能嵌套！
 DTO不支持嵌套关联：DTO do not work with native queries不支持原生语句.
 Dynamic Projections投影 # <T> Collection<T> findByLastname(String lastname, Class<?> type);
 类同查询： Example<Person> example = Example.of(person, matcher);
 其实 save() 对JPA非必须, 统一规范Spring Data需要用。
 /? /orm.xml配置文件；审计： @EnableJpaAuditing@Configuration ；非正常：CDI @Inject xxRepository
 实体类投影方式：投影代理    https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
 没重载的基本方法不能用于投影。@Query注释 将重写的基本方法转换为查询方法，然后可以使用该方法返回 投影。
 interface PersonSummary {  投影:仅仅获取一部分的实体类字段
      String getFirstname();
      String getLastname();
      AddressSummary getAddress();  #嵌套的关联也可以 投影；
      interface AddressSummary {
        String getCity();
      }
 }  开放投影：接口中的访问器方法也可以通过@Value注释SpEL来计算新值

https://hibernate.org/orm/6版本？ 要等到Boot 3.0之后支持需被替换很大的包jakarta.persistence to jakarta.persistence 3.1
JPA规范 @PostLoad  CriteriaQuery<Tuple> 6.5.7. Downcasting  cb.<String>selectCase()  CriteriaQuery<CustomerDetails> em.getMetamodel;
EntityManager单线程事务  https://jakarta.ee/specifications/persistence/3.1/jakarta-persistence-spec-3.1.html

牺牲部分便利性为 @ManyToOne注解添加 fetch = FetchType.LAZY属性 https://www.sohu.com/a/378958510_505818
读数据库尽量加上@Transactional确保整个接口函数分多次读取DB相关记录的一致性。 https://stackoverflow.com/questions/53325506/criteria-api-vs-querydsl-vs-jpa-metamodel
createNativeQuery太麻烦了@SqlResultSetMapping{@ConstructorResult({)  https://www.it1352.com/1477280.html
findAll(new Specification<Isp>(), pageable)这个toPredicate会执行两次(第二个count()),不加复杂过滤还是会把Eqp都查出还是生成慢查询SQL

旧的Future异步编程，新的Reactive Reactor编程屏蔽底层并发细节 背压,WebFlux； springCould 常见组件Feign配套REST;
RSocket 是TCP/IP之上的应用层协议支持TCP、ws和UDP,rsocket-transport-netty不需要监听的;
异步R2DBC简易映射实体而不是ORM同步 WebFlux，R2DBC是过渡技术？r2dbc-postgresql; r2dbc vs jpa:同步与异步;
并发道路Future=>NIO=>Reactor|CompletableFuture|Flow=>协程=> Loom 虚拟线程。
mockito单元测试；
*/
